<script setup lang="ts">
import mapboxgl, { GeoJSONSource, LngLatLike } from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';

import { inject, onMounted, ref } from 'vue';
import ProvincePopup from './ProvincePopup.vue';

const global = inject('global');
const get = global['get'];

mapboxgl.accessToken = 'pk.eyJ1IjoiZmVuZ3NodW9rZWppIiwiYSI6ImNsamh5Y3F4dzBsenAzb242MWxlb2RlMGEifQ.en9743EghxSChSSkucqjfA';
let map: mapboxgl.Map;

const props = defineProps({
  extType: {
    type: String,
    default: () => 'school,workstation'
  }
});

onMounted(() => {
  map = new mapboxgl.Map({
    container: 'map',
    style: {
      version: 8,
      sources: {
        land: {
          type: 'geojson',
          data: {
            type: 'FeatureCollection',
            features: []
          }
        },
        province: {
          type: 'geojson',
          data: {
            type: 'FeatureCollection',
            features: []
          }
        },
        schoolProvince: {
          type: 'geojson',
          data: {
            type: 'FeatureCollection',
            features: []
          }
        },
        school: {
          type: 'geojson',
          data: {
            type: 'FeatureCollection',
            features: []
          }
        }
      },
      glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
      layers: [
        {
          id: 'land',
          type: 'fill',
          source: 'land',
          paint: {
            'fill-color': '#E8E8E8'
          }
        },
        {
          id: 'province',
          type: 'line',
          source: 'land',
          paint: {
            'line-color': '#000000'
          }
        },
        {
          id: 'province-circles',
          type: 'circle',
          source: 'province',
          layout: {},
          paint: {
            'circle-color': '#27BFBF', // 设置颜色为绿色
            'circle-radius': 5, // 设置圆的半径，根据需要调整
            'circle-stroke-width': 1,
            'circle-stroke-color': '#03FDF0' // 可选，为圆圈添加白色边框
          }
        },
        {
          id: 'province-labels',
          type: 'symbol',
          source: 'province',
          layout: {
            'text-field': '{name}',
            'text-size': 12,
            'text-offset': [0, 1],
            'text-anchor': 'top',
            'text-justify': 'center',
            'symbol-placement': 'point'
          },
          paint: {
            'text-color': '#000000'
          }
        },
        {
          id: 'school-fill',
          type: 'fill',
          source: 'schoolProvince',
          paint: {
            'fill-color': 'red',
            'fill-opacity': ['case', ['boolean', ['feature-state', 'hover'], false], 0.6, 0.35]
          }
        }
      ]
    },
    // zoom: 3,
    // maxZoom: 14,
    maxBounds: [
      [56.4833, 3.3166], // 大致为最西端和最南端的坐标，稍作调整以包括整个国土
      [155.05, 53.55] // 大致为最东端和最北端的坐标，同样稍作调整
    ],
    center: [103.823557, 50.058039],
    dragPan: false,
    dragRotate: false,
    touchZoomRotate: false,
    pitchWithRotate: false,
    keyboard: false,
    doubleClickZoom: false,
    scrollZoom: false,
    boxZoom: false,
    touchPitch: false,
    logoPosition: 'bottom-right'
  });

  map.on('style.load', async () => {
    map.setFog({
      color: 'rgba(0,0,0,0)'
    });

    map.on('mousemove', 'school-fill', e => {
      map.getCanvas().style.cursor = 'pointer';
      if (e.features.length <= 0) {
        return;
      }

      if (hoveredPolygonId.value !== null) {
        map.setFeatureState({ source: 'schoolProvince', id: hoveredPolygonId.value }, { hover: false });
      }
      hoveredPolygonId.value = e.features[0]['id'];
      map.setFeatureState({ source: 'schoolProvince', id: hoveredPolygonId.value }, { hover: true });
    });

    map.on('mouseleave', 'school-fill', () => {
      map.getCanvas().style.cursor = '';
      if (hoveredPolygonId.value !== null) {
        map.setFeatureState({ source: 'schoolProvince', id: hoveredPolygonId.value }, { hover: false });
      }
      hoveredPolygonId.value = null;
    });

    map.on('click', 'school-fill', e => {
      if (e.features.length <= 0) {
        return;
      }
      let feature = e.features[0];
      showPopupByFeature(feature);
    });

    // 加载省数据
    loadProvinceData().catch();
  });

  // 监听窗口大小变化并调整地图尺寸
  window.addEventListener('resize', () => {
    map.resize();
  });
});

let provincePopup = ref(null),
  provinceData = ref(null),
  hoveredPolygonId = ref(null),
  popupItem = ref({});

let popup = null;

const showPopupByFeature = async (feature: object) => {
  const properties = feature['properties'];
  const center = properties['centroid'] || properties['center'];
  const subjectId = feature['id'];
  let data = { subjectId, name: properties['name'], allEmpty: properties.allEmpty };
  let titles = props.extType.split(',');
  titles.forEach(item => {
    data[item] = JSON.parse(properties[item]);
  });
  data['title'] = titles;
  popupItem.value = data;
  popup?.remove();
  popup = new mapboxgl.Popup().setLngLat(JSON.parse(center)).addTo(map);
  popup.setDOMContent(provincePopup.value.$el);
};

const showItem = (item: any) => {
  let province = item.ext.province;
  let element = provinceData.value.find((feature: any) => feature['properties'].name === province);
  if (!element) {
    return;
  }
  hoveredPolygonId.value = element.id;
  const properties = element['properties'];
  let titles = props.extType.split(',');
  popupItem.value = {
    subjectId: element.id,
    name: properties['name'],
    title: titles
  };
  popupItem.value[item.ext.type] = [item];
  let center = properties['centroid'] || properties['center'];
  if (center) {
    popup?.remove();
    popup = new mapboxgl.Popup().setLngLat(center).addTo(map);
    popup.setDOMContent(provincePopup.value.$el);
    popup.on('close', () => onHidePopup(item.id));
  }
};

/**
 * 获取学校专题数据，从中获取省份数据
 */
const getMapData = () =>
  new Promise(async resolve => {
    let res = await get('knowledge/provinceMap', { ext: { type: props.extType } });
    let mapData = res || {};
    let dataList = mapData['data'] || [];
    onDataListChange(dataList);
    resolve(mapData);
  });

/**
 * 获取边界数据
 */
const fetchGeo = async () => {
  const key = 'boundGeoJson';
  const geojson = localStorage.getItem(key);
  if (geojson) {
    return JSON.parse(geojson);
  }
  let bound = await get('/bound/geojson?code=100000_full');
  localStorage.setItem(key, JSON.stringify(bound));
  return bound;
};

/**
 * 加载省数据
 */
const loadProvinceData = async () => {
  const [geojson, mapData] = await Promise.all([fetchGeo(), getMapData()]);
  const province = mapData['province'] as Array<object>;
  const data = mapData['data'] as Array<object>;

  let countrySource: GeoJSONSource = map.getSource('land') as GeoJSONSource;
  countrySource.setData(geojson);

  const centerFeatures: Array<any> = [];
  const provinceFeature: Array<any> = [];
  geojson.features.forEach((element: object) => {
    const properties = element['properties'];
    // 遍历省份，根据名称匹配省份
    const name = properties['name'];
    province?.forEach((p: object) => {
      if (p['title'].indexOf(name) > -1) {
        element['id'] = p['id'];
        const properties = element['properties'];
        provinceFeature.push(element);
        let filterData = data.filter((s: any) => s['ext']['province'] === name);
        properties.school = filterData.filter((s: any) => s['ext']['type'] === 'school');
        properties.workstation = filterData.filter((s: any) => s['ext']['type'] === 'workstation');
        properties.allEmpty = filterData.length === 0;
      }
    });
    let center = properties['centroid'] || properties['center'];
    if (center) {
      let feature = Object.assign({}, element, {
        geometry: {
          type: 'Point',
          coordinates: center
        }
      });
      centerFeatures.push(feature);
    }
  });
  provinceData.value = provinceFeature;

  let labelSource: GeoJSONSource = map.getSource('province') as GeoJSONSource;
  labelSource.setData({ type: 'FeatureCollection', features: centerFeatures });

  let schoolProvinceSource: GeoJSONSource = map.getSource('schoolProvince') as GeoJSONSource;
  schoolProvinceSource.setData({ type: 'FeatureCollection', features: provinceFeature });
};

/**
 * 调整地图尺寸
 */
const resizeMap = () => {
  map.resize();
};

// 使用 defineExpose 来暴露函数
defineExpose({
  resizeMap,
  showItem
});

const emits = defineEmits(['hidePopup', 'schoolList']);

const onHidePopup = (id: number) => {
  emits('hidePopup', id);
};
const onDataListChange = (school: any) => {
  emits('schoolList', school);
};
</script>

<template>
  <div>
    <!--    <img src="../assets/mock/8.png" alt="" />-->
    <div id="map" class="map-container"></div>
    <ProvincePopup ref="provincePopup" :v-show="hoveredPolygonId" :popupContent="popupItem" />
  </div>
</template>

<style scoped lang="scss">
.map-container {
  //position: absolute;
  //top: 0;
  //left: 0;
  width: 100%;
  height: 577px;
}
</style>
